#!/usr/bin/env python
# coding=utf-8
from flask import render_template, flash, redirect, url_for, Blueprint, current_app, request
from flask_login import login_user, logout_user, login_required, current_user
from fileshare.forms import LoginForm, RegistrationForm, PasswordResetForm
from fileshare.models import Admin
from fileshare.utils import redirect_back
from fileshare.emails import send_mail
from fileshare.extensions import db, csrf
import os


auth_bp = Blueprint('auth', __name__)


@auth_bp.before_app_request
def before_request():
    if current_user.is_authenticated:
        current_user.ping()
        if not current_user.confirmed \
                and request.endpoint \
                and request.endpoint[:5] != 'auth.' \
                and request.endpoint != 'static':
            return redirect(url_for('auth.unconfirmed'))


@auth_bp.route('/<string:key>/', methods=['GET', 'POST'])
def login(key):
    if current_app.config['SECURE_LINK']:
        if key != current_app.config['SECURE_LINK']:
            return redirect(url_for('auth.error'))
    if current_user.is_authenticated:
        return redirect(url_for('main.index'))
    form = LoginForm()
    if form.validate_on_submit():
        username = form.username.data
        password = form.password.data
        remember = form.remember.data
        admin = Admin.query.filter_by(username=username).first()
        if admin and admin.verify_password(password):
            login_user(admin, remember)
            flash('登录成功', 'success')
            return redirect_back()
        flash('用户名或密码无效', 'warning')
    return render_template('auth/login.html', form=form)


@auth_bp.route('/error', methods=['GET', 'POST'])
def error():
    return '请使用安全链接'


@auth_bp.route('/logout')
@login_required
def logout():
    logout_user()
    flash('退出成功', 'success')
    return redirect(url_for('auth.login', key=current_app.config['SECURE_LINK']))


@auth_bp.route('/register', methods=['GET', 'POST'])
def register():
    form = RegistrationForm()
    if form.validate_on_submit():
        user = Admin(email=form.email.data,
                     username=form.username.data,
                     password=form.password.data)
        user.filenames = user.get_filenames()
        db.session.add(user)
        db.session.commit()
        token = user.generate_confirmation_token()
        confirm_url = url_for(
            'auth.confirm', token=token, _external=True)
        html = render_template('auth/email/auth-confirm.html',
                               username=user.username, confirm_url=confirm_url)
        send_mail('验证你的帐号', user.email,
                  html=html)
        flash('已经向您的邮箱发送了一份确认邮件', 'success')
        return redirect(url_for('auth.login', key=current_app.config['SECURE_LINK']))
    return render_template('auth/register.html', form=form, key=current_app.config['SECURE_LINK'])


@auth_bp.route('/confirm/<token>', methods=['GET'])
def confirm(token):
    if not current_user.is_authenticated:
        flash('请登录来访问此页面', 'warning')
        return redirect(url_for('auth.login', key=current_app.config['SECURE_LINK']))
    if current_user.confirmed:
        return redirect(url_for('main.index'))
    if current_user.confirm(token):
        flash('您已确认您的帐户,谢谢!', "success")
    else:
        flash('确认链接无效或已过期', 'warning')
    return redirect(url_for('main.index'))


@auth_bp.route('/confirm')
@login_required
def resend_confirmation():
    token = current_user.generate_confirmation_token()
    confirm_url = url_for(
        'auth.confirm', token=token, _external=True)
    html = render_template('auth/email/auth-confirm.html',
                           username=current_user.username, confirm_url=confirm_url)
    send_mail('验证你的帐号', current_user.email,
              html=html)
    flash('一个新的确认邮件已经通过电子邮件发送给你', "info")
    return redirect(url_for('main.index'))


@auth_bp.route('/unconfirmed')
def unconfirmed():
    if current_user.is_anonymous or current_user.confirmed:
        return redirect(url_for('main.index'))
    return render_template('auth/unconfirmed.html')


@csrf.exempt
@auth_bp.route('/reset', methods=['GET', 'POST'])
def password_reset_request():
    if not current_user.is_anonymous:
        return redirect(url_for('main.index'))
    if request.method == 'POST':
        email = request.values.get('email')
        user = Admin.query.filter_by(email=email).first()
        if user:
            token = user.generate_reset_token()
            confirm_url = url_for(
                'auth.password_reset', token=token, _external=True)
            html = render_template('auth/email/reset-confirm.html',
                                   username=user.username, confirm_url=confirm_url)
            send_mail('重置你的密码', email,
                      html=html)
            flash('已发送一封电子邮件，要求你重置密码', 'info')
        return redirect(url_for('auth.login', key=current_app.config['SECURE_LINK']))
    return render_template('auth/forgot-password.html', key=current_app.config['SECURE_LINK'])


@auth_bp.route('/reset/<token>', methods=['GET', 'POST'])
def password_reset(token):
    if not current_user.is_anonymous:
        return redirect(url_for('main.index'))
    form = PasswordResetForm()
    if form.validate_on_submit():
        user = Admin.query.filter_by(email=form.email.data).first()
        if user is None:
            flash('未知的用户', 'warning')
            return redirect_back()
        if user.reset_password(token, form.password.data):
            flash('您的密码已更新', 'info')
            return redirect(url_for('auth.login', key=current_app.config['SECURE_LINK']))
        else:
            flash('邮箱验证失败', 'warning')
            return redirect_back()
    return render_template('auth/reset-password.html', form=form, key=current_app.config['SECURE_LINK'])
